package com.fengwei.verify;

import com.fengwei.util.RuntimeUtil;
import com.fengwei.annotation.Condition;
import com.fengwei.util.EnumUtil;
import com.fengwei.util.VerifyEnum;
import com.fengwei.util.VerifyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;

public class Verify {
    private final static Logger logger = LoggerFactory.getLogger(Verify.class);

    public static boolean isEmpty(String string) {
        if (string == null) {return true;}
        if (string.length() == 0) {return true;}
        return false;
    }

    public static boolean isEmpty(Object object) {
        if (object instanceof String) {
            return Verify.isEmpty((String) object);
        }
        if (object == null) {return true;}
        return false;
    }

    /**
     * @Description: 结合spring内置参数校验注解对参数进行数据验证。
     * @Param: object
     * @return: void
     * @Author: JamesLee
     * @Date: 2019/8/21
     */
    public static void verifyData(Object object) throws Exception {
        Field[] fields = RuntimeUtil.getFields(object);
        VerifyException exception = new VerifyException();
        StringBuilder stringBuilder = new StringBuilder();
        boolean ifException = false;
        for (Field field : fields) {
            field.setAccessible(true);
            boolean notNullFlag = Verify.addNotNullCheck(field, object, stringBuilder);
            boolean patternFlag = Verify.addPatternCheck(field, object, stringBuilder);
            boolean conditionFlag = Verify.addConditionCheck(field, object, stringBuilder);
            if (!ifException) {
                if (!notNullFlag || !patternFlag || !conditionFlag) {
                    ifException = true;
                }
            }
        }
        if (ifException) {
            String resultMsg = stringBuilder.toString();
            resultMsg = resultMsg.substring(0, resultMsg.length() - 1);
            EnumUtil.changeDes(VerifyEnum.RESULT_PARAM_ERROR, resultMsg);
            exception.setErrorStatus(VerifyEnum.RESULT_PARAM_ERROR);
            throw exception;
        }
    }

    public static void verifyDataByValidation(Object object, Class<?>... groups) throws InvocationTargetException, IllegalAccessException {
        VerifyException exception = new VerifyException();
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        Iterator<ConstraintViolation<Object>> it = constraintViolations.iterator();
        while (it.hasNext()) {
            ConstraintViolation<Object> constraintViolation = it.next();
            if (constraintViolation != null) {
                logger.error(constraintViolation.getMessage());
                EnumUtil.changeDes(VerifyEnum.RESULT_PARAM_ERROR, constraintViolation.getMessage());
                exception.setErrorStatus(VerifyEnum.RESULT_PARAM_ERROR);
                throw exception;
            }
        }
        logger.debug("Request Model Validate [ OK ]");
    }

    /**
     * @Description: 当检查存在空时返回false
     * @Param:
     * @return:
     * @Author: JamesLee
     * @Date: 2019/8/21
     */
    private static boolean addNotNullCheck(Field field, Object object, StringBuilder resultMsg) throws IllegalAccessException {
        if (field.isAnnotationPresent(NotNull.class) && Verify.isEmpty(field.get(object))) {
            NotNull notNull = field.getAnnotation(NotNull.class);
            resultMsg.append(notNull.message());
            resultMsg.append(",");
            return false;
        }
        return true;
    }

    /**
     * @Description: 当检查存在不符合正则条件时返回false
     * @Param:
     * @return:
     * @Author: JamesLee
     * @Date: 2019/8/21
     */
    private static boolean addPatternCheck(Field field, Object object, StringBuilder resultMsg) throws IllegalAccessException {
        if (field.isAnnotationPresent(Pattern.class)) {
            Pattern pattern = field.getAnnotation(Pattern.class);
            java.util.regex.Pattern pattern1 = java.util.regex.Pattern.compile(pattern.regexp());
            //只校验该对象的正则，不处理当对象为空的情况。
            if (field.get(object) == null) {return true;}
            Matcher matcher = pattern1.matcher((String) field.get(object));
            if (!matcher.matches()) {
                resultMsg.append(pattern.message());
                resultMsg.append(",");
                return false;
            }
        }
        return true;
    }

    private static boolean addConditionCheck(Field field, Object object, StringBuilder resultMsg) throws Exception {
        if (field.isAnnotationPresent(Condition.class)) {
            Condition condition = field.getAnnotation(Condition.class);
            String[] conditions = condition.conditions();
            String property = condition.onProperty();
            Field propertyField = object.getClass().getDeclaredField(property);
            boolean flag = true;
            for (String tempCondition : conditions) {
                if (!Verify.isEmpty(propertyField.get(object))) {
                    if (propertyField.get(object).equals(tempCondition)) {
                        if (flag) {
                            if (Verify.isEmpty(field.get(object))) {
                                flag = false;
                            }
                        }
                    }
                }
            }
            if (!flag) {
                resultMsg.append(condition.message());
                resultMsg.append(",");
            }
            return flag;
        }
        return true;
    }
}
